package com.ct.extension.config;

import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.transaction.RabbitTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitTemplateConfig {

    // 这里要创建一个新的没有回调函数的 RabbitTemplate 给 Spring 容器保管
    // 因为 Bean 是先根据类型来寻找的, 我们创建了一个又回调函数的类, 默认没有
    // 回调函数的方法 Spring 已经不会帮我们创建了
    @Bean("rabbitTemplate")
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        return rabbitTemplate;
    }

    @Bean("confirmRabbitTemplate")
    public RabbitTemplate confirmRabbitTemplate(ConnectionFactory connectionFactory){

        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);

        // 设置回调方法
        // 若在此处设置回调函数，那么会影响到所有 rabbitTemplate
        // 并且只能发送一次消息，因为发送多次消息就相当于设置了多个回调函数，规定只能设置一次
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("执行了 confirm 方法");
                if (ack) {

                    // 消息到达了交换机
                    System.out.printf("接收到信息, 消息 ID: %s \n",
                            correlationData == null ? null : correlationData.getId());
                } else {

                    // 消息未到达交换机
                    System.out.printf("未接收到信息, 消息 ID: %s, cause: %s \n",
                            correlationData == null ? null : correlationData.getId(), cause);
                    // 响应业务的处理
                    System.out.println("相应的业务处理");
                }
            }
        });

        // 消息被退回时, 回调方法
        rabbitTemplate.setMandatory(true); // 启动强制路由检查
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returned) {
                System.out.println("消息退回:"+returned);
            }
        });
        return rabbitTemplate;
    }

    @Bean("transRabbitTemplate")
    public RabbitTemplate transRabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setChannelTransacted(true);  //开启事务
        return rabbitTemplate;
    }

    @Bean
    public RabbitTransactionManager rabbitTransactionManager(ConnectionFactory connectionFactory){
        return new RabbitTransactionManager(connectionFactory);
    }

}
